"use strict";
// 一些工具
const sys = {
	getEl: params => document.querySelector(params),
	getEls: params => document.querySelectorAll(params),
	// 事件总线:
	on: function() {},
	emit: function() {},
	_arrOnEvent: [],
	// 处理先emit后on的情况,将漫游中的emit'暂存'
	_arrCacheEmit: [{}, {}]
};

/**
 * @description 检测数据类型
 * @param {*} variable
 * @returns {String} type 返回类型,首字母大写
 */
sys.getType = function(variable) {
	// 11种
	// console.log(Object.prototype.toString.call("sstr"));//[object String]
	// console.log(Object.prototype.toString.call(12));//[object Number]
	// console.log(Object.prototype.toString.call(true));//[object Boolean]
	// console.log(Object.prototype.toString.call(undefined));//[object Undefined]
	// console.log(Object.prototype.toString.call(null));//[object Null]
	// console.log(Object.prototype.toString.call({}));//[object Object]
	// console.log(Object.prototype.toString.call(function () { }));//[object Function]
	// console.log(Object.prototype.toString.call([]));//[object Array]
	// console.log(Object.prototype.toString.call(new Date));//[object Date]
	// console.log(Object.prototype.toString.call(/\d/));//[object RegExp]
	//!! console.log(Object.prototype.toString.call(Symbol));//[object Function] !!
	//console.log(Object.prototype.toString.call(Symbol()));//[object Symbol]
	var type = Object.prototype.toString.call(variable).slice(8, -1);
	return type;
};

/**
 * @description 根据on与emit的参数执不同的策略
 * @param {String | Array} eventName
 * @param {Function} callback
 */
sys._eventPublicCheckArgType = function(eventName, callback) {
	let arrEventName = [];
	if (Array.isArray(eventName) && eventName.length > 0) {
		//console.log("数组");
		arrEventName = eventName;
	} else if (
		typeof eventName == "string" &&
		eventName.trim().length > 0 &&
		eventName.split(",").length > 1
	) {
		//console.log("多字符串拆数组");
		arrEventName = eventName.split(",");
	} else if (
		typeof eventName == "string" &&
		eventName.trim().length > 0 &&
		eventName.split(",").length == 1
	) {
		//console.log('单字符串还原数组');
		arrEventName = [eventName];
	} else {
		console.error("未知类型");
	}
	callback.call(this, arrEventName);
};

/**
 * @description 发送事件
 * @param {String | Array} eventName
 * @param {*} params
 */
sys.emit = function(eventName, params) {
	let sItemEvent = "";
	function funCheckArrFunHaveEventName(arrEventName) {
		var arrEventNameLen = arrEventName.length;
		for (let i = 0; i < arrEventNameLen; i++) {
			(i => {
				let isHaveEvent = this._arrOnEvent.some((item, index) => {
					sItemEvent = item;
					return item.name == arrEventName[i];
				});
				if (isHaveEvent) {
					sItemEvent.fun(params);
					return true;
				} else {
					console.error(eventName, "该事件未被监听,emit被挂起");
					this._arrCacheEmit.push({ name: eventName, param: params });
					return false;
				}
			})(i);
		}
	}
	sys._eventPublicCheckArgType.call(
		this,
		eventName,
		funCheckArrFunHaveEventName
	);
};

/**
 * @description 监听事件
 * @param {String | Array} eventName
 * @param {Function} [callback=function () { }]
 */
sys.on = function(eventName, callback = function() {}) {
	function funAddon(arrEventName) {
		if (sys.getType(callback) === "Function") {
			// 先检查存在漫游事件
			this._arrCacheEmit.forEach(function(item, index) {
				for (let i = 0; i < arrEventName.length; i++) {
					// item.name == arrEventName[i].name可能都为undefined....
					if (
						item.name &&
						arrEventName[i] &&
						item.name == arrEventName[i]
					) {
						//有漫游
						callback(item.param);
						console.log(item.name, arrEventName[i]);
					} else {
						this._arrOnEvent.push({
							name: eventName,
							fun: callback.bind(this)
						});
					}
				}
			}, this);
		} else {
			console.error(callback + " is not function");
		}
	}
	this._eventPublicCheckArgType.call(this, eventName, funAddon);
};

// 个性域名正则 字幕开头,只能包含字母 - _ 数字 , 2 - 34位可以字幕数字下划线连接符 , 结尾不允许特殊字符结尾
// let reUserdomainName = /^[a-zA-Z]{1}[a-zA-Z\-_0-9]{1,34}/gi;
// 上面正则第一次test('aA')正确,第二次错误 , 不应该写/g   , 写全局匹配导致lastIndex改变 下一次才lastIndex继续匹配
// ^ 匹配第一个字符 , [^0-9] 匹配除数字以外的字符
//  let reUserdomainName = /^[a-zA-Z]{1}[a-zA-Z\-_0-9]{0,33}[a-zA-Z0-9]{1,}$/i; 字符数大于35也是true,验证字符数 类似于每一段可匹配数相加

/**
 * @description 校验个性域名
 * @author 衣沾不足惜 javascript.h@qq.com
 * @date 2020-05-04
 * @param domain
 * @returns Boolean
 */
function checkUserdomainName(domain) {
	if (!domain) {
		console.error("params error:" + value);
		return false;
	}
	let reUserdomainName = /^[a-zA-Z]{1}[a-zA-Z\-_0-9]{0,33}[a-zA-Z0-9]{1}$/i;
	if (reUserdomainName.test(domain)) return true;
	return false;
}
/**
 * @description  校验手机 除10 11 12开头以外的手机号码几乎都存在
 * @author 衣沾不足惜 javascript.h@qq.com
 * @date 2020-05-04
 * @param value
 * @returns
 */
function checkPhone(value) {
	if (!value) {
		console.error("params error:" + value);
		return false;
	}
	if (!/^1[3456789]\d{9}$/.test(value)) {
		return false;
	}
	return true;
}
/**
 * @description 校验邮箱
 * @author 衣沾不足惜 javascript.h@qq.com
 * @date 2020-05-04
 * @param value
 * @returns
 */
function checkEmail(value) {
	if (!value) {
		console.error("params error:" + value);
		return false;
	}
	// 字母数字开头一次及以上 , (-字母数字一次以上 或 .字母数字一次以上 或 _字母数字一次以上 或纯字母数字一次以上 )(整体一次以上), @ 字母或数字一次以上 . 字母或数字两次以上
	let reEmail = /^[a-zA-Z0-9]{1,}(\-[a-zA-Z0-9]{1,}|\.[a-zA-Z0-9]{1,}|\_[a-zA-Z0-9]{1,}|[a-zA-Z0-9]|[a-zA-Z0-9]){1,}\@([a-zA-Z0-9]{1,}\.[a-zA-Z0-9]{2,})/;
	if (!reEmail.test(value)) {
		return false;
	}
	return true;
}

/**
 * @description 防抖
 * @author 衣沾不足惜 javascript.h@qq.com
 * @date 2020-05-04
 * @param fn
 * @param [time=200]
 * @returns
 */
function debounce(func, delay) {
	let timeout;
	// timeout只初始化一次 ,后续调用实际上是返回的函数
	return function(e) {
		clearTimeout(timeout);
		// this 指向调用者 ,addEventListener中为dom对象
		// e.target.value
		let context = this;
		timeout = setTimeout(function() {
			func.call(context, e);
		}, delay);
	};
}
